using System.Linq;
using System.Net;
using System.Text;
using IDeal.Attributes;
using IDeal.Exceptions;
using IDeal.Models;
using IDeal.Serialization;
using IDeal.Services;

namespace IDeal.Net
{
    public class XmlWebClient : IXmlWebClient
    {
        private readonly IIDealServices _iDealServices;
        private readonly WebClient _webClient;

        public XmlWebClient(IIDealServices iDealServices)
        {
            _iDealServices = iDealServices;
            _webClient = new WebClient();
        }

        public TResponse SendRequest<TRequest, TResponse>(TRequest request) where TRequest: XmlRequest where TResponse : XmlResponse
        {
            _webClient.Headers.Add(HttpRequestHeader.ContentType, "text/xml");

            var requestXml = CreateRequestXml(request);
            var url = _iDealServices.Configuration.ApiUrl;
            var responseData = _webClient.UploadData(url, "POST", Encoding.UTF8.GetBytes(requestXml));
            var responseXml = Encoding.UTF8.GetString(responseData);

            if (responseXml.Contains("ErrorRes"))
            {
                var errorReader = new ErrorResponseXmlReader(_iDealServices);
                var error = errorReader.FromXml(responseXml);
                throw new ErrorResponseException(error);
            }

            return ParseResponseXml<TResponse>(responseXml);
        }

        private string CreateRequestXml<T>(T request)
        {
            var requestType = request.GetType();
            var requestSerializerAttribute = (XmlAdapterAttribute)requestType.GetCustomAttributes(typeof(XmlAdapterAttribute), true).FirstOrDefault();
            var requestSerializerType = requestSerializerAttribute.Type;
            var requestSerializer = _iDealServices.Activator.CreateInstance<IXmlMessageWriter<T>>(requestSerializerType, _iDealServices);
            return requestSerializer.ToXml(request);
        }

        private T ParseResponseXml<T>(string xml) where T : XmlResponse
        {
            var responseType = typeof (T);
            var serializerAttribute = (XmlAdapterAttribute)responseType.GetCustomAttributes(typeof(XmlAdapterAttribute), true).FirstOrDefault();
            var serializerType = serializerAttribute.Type;
            var serializer = _iDealServices.Activator.CreateInstance<IXmlMessageReader<T>>(serializerType, _iDealServices);
            return serializer.FromXml(xml);
        }
    }
}